import paho.mqtt.client as mqtt
import time
import json

class MQTTSubscriber:
    def __init__(self, broker="47.93.172.78", port=1883,
            keepalive=60,topic="default/topic",device_id="default_device"):
        self.broker = broker
        self.port = port
        self.keepalive = keepalive
        self.current_topic = topic
        self.device_id = device_id
        self.client = mqtt.Client(
                callback_api_version=mqtt.CallbackAPIVersion.VERSION2
                )
        self.client.on_connect = self._on_connect
        self.client.on_message = self._on_message

        # 设置遗嘱消息（关键！）
        self.client.will_set(
            topic="status/topic",  
            payload=json.dumps({"deviceId": self.device_id, "state": "disable"}),
            qos=1,
            retain=True
        )
        try:
            self.client.connect(self.broker, self.port, self.keepalive)
            self.subscribe()
            self.client.loop_forever()  # 保持持续监听
        except KeyboardInterrupt:
            self.client.publish("status/topic", json.dumps({"deviceId": self.device_id, "state": "disable"}), qos=1, retain=True)
            print("\n停止订阅")
            self.client.disconnect()
        except Exception as e:
            self.client.publish("status/topic", json.dumps({"deviceId": self.device_id, "state": "disable"}), qos=1, retain=True)
            print(f"[Subscriber] 错误: {e}")
            self.client.disconnect()

    def _on_connect(self, client, userdata, flags, rc, properties=None):
        if rc == 0:
            print(f"Subscriber connected to {self.broker}:{self.port} with code {rc}")
            client.publish("status/topic", json.dumps({"deviceId": self.device_id, "state": "active"}), qos=1, retain=True)  # 发布在线状态
        else:
            print(f"[Subscriber] Connection failed: {rc}")
   
    def _on_message(self, client, userdata, msg):
        """收到消息时的回调"""
        print(f"Received `{msg.payload.decode()}` from `{msg.topic}`")

    def subscribe(self):
        """暴露的接口：动态修改订阅主题"""
        result = self.client.subscribe(self.current_topic)
        if result[0] == mqtt.MQTT_ERR_SUCCESS:
            print(f"Subscribed to `{self.current_topic}`")
        else:
            print(f"Failed to subscribe to `{topic}`")
if __name__ == "__main__":
    subscriber = MQTTSubscriber()
